package com.situ.shoplook.dubbo.service.impl;

import com.situ.shoplook.common.model.Category;
import com.situ.shoplook.common.service.CategoryService;
import com.situ.shoplook.dubbo.dao.CategoryDao;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Stream;

/**
 * 功能：
 *
 * @author 千堆雪
 * @version 1.0.0
 * <p>
 * created by 千堆雪 on 2024/8/24, last modified by 千堆雪 on 2024/8/24
 */
@CacheConfig(cacheNames = "com.situ.shoplook.service.impl.CategoryServiceImpl")
@Service
public class CategoryServiceImpl implements CategoryService {
    private CategoryDao categoryDao;

    @Autowired
    public void setCategoryDao(CategoryDao categoryDao) {
        this.categoryDao = categoryDao;
    }

    /**
     * 使用缓存
     *
     * @return 所有类别实例
     */
    @Cacheable(keyGenerator = "customKeyGenerator")
    @Override
    public List<Category> findAll() {
        return this.categoryDao.findAll();
    }

    /**
     * 不单独从数据中获取，而直接从findTree的缓存中获取，因为findTree已处理成树型结构
     *
     * @param id 类别编号
     * @return 指定编号的类别
     */
    @Cacheable(keyGenerator = "customKeyGenerator")
    @Override
    public Category findById(Integer id) {
        //返回当前实现的代理对象
        CategoryService cs = (CategoryService) AopContext.currentProxy();
        //如此调用才能触发代理，如果直接this.findAll()，那么由于this并不是代理实例，无法触发aop
        Category root = cs.findTree();
        return root.deepFindById(id);
    }

    @Cacheable(keyGenerator = "customKeyGenerator")
    @Override
    public Category findTree() {
        //返回当前实现的代理对象
        CategoryService cs = (CategoryService) AopContext.currentProxy();
        //如此调用才能触发代理，如果直接this.findAll()，那么由于this并不是代理实例，无法触发aop
        List<Category> categories = cs.findAll();
        return Category.buildCategoryTree(categories);
    }

    /**
     * 安全删除，要考虑是否有子节点，以及是否此类别下有商品
     *
     * @param id      要删除的主键
     * @param cascade 是否级联删除
     * @return 成功删除行数
     */
    @Transactional
    @CacheEvict(allEntries = true)
    @Override
    public int deleteById(Integer id, boolean cascade) {
        int count = 0;
        //返回当前实现的代理对象
        CategoryService cs = (CategoryService) AopContext.currentProxy();
        //如此调用才能触发代理，如果直接this.findAll()，那么由于this并不是代理实例，无法触发aop
        Category category = cs.findById(id);

        if (category != null) {
            List<Category> children = category.getChildren();
            if (!CollectionUtils.isEmpty(children)) {
                if (cascade) {
                    count = children.stream().mapToInt(t -> cs.deleteById(t.getId(), true)).sum();
                } else {
                    throw new RuntimeException("子节点不为空，无法删除");
                }
            }

            boolean b = this.categoryDao.delete(category);
            if (b) {
                count++;
            }
        }

        return count;
    }

    @Transactional
    @CacheEvict(allEntries = true)
    @Override
    public int deleteByIds(Integer[] ids, boolean cascade) {
        //返回当前实现的代理对象
        CategoryService cs = (CategoryService) AopContext.currentProxy();
        //如此调用才能触发代理，如果直接this.findAll()，那么由于this并不是代理实例，无法触发aop
        return Stream.of(ids).mapToInt(t -> cs.deleteById(t, cascade)).sum();
    }

    @CacheEvict(allEntries = true)
    @Override
    public boolean save(Category category) {
        return this.categoryDao.save(category) > 0;
    }

    @CacheEvict(allEntries = true)
    @Override
    public boolean update(Category category) {
        return this.categoryDao.update(category) > 0;
    }
}
